package com.eurasia.assignment.service;

import com.eurasia.assignment.controller.dto.FileUploadResponse;
import com.eurasia.assignment.domain.FileStorage;
import com.eurasia.assignment.infrastructure.entity.FileEntity;
import com.eurasia.assignment.infrastructure.repository.FileRepository;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.support.ServletUriComponentsBuilder;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.util.Objects;
import java.util.UUID;
import java.util.concurrent.atomic.AtomicInteger;

@Service
@RequiredArgsConstructor
@Slf4j
public class FileService {

    private final FileRepository fileRepository;
    private final FileStorage fileStorage;
    private final AtomicInteger sequenceCounter = new AtomicInteger(1);

    @Value("${file.upload-dir:./uploads}")
    private String uploadDir;

    public FileUploadResponse storeFile(MultipartFile file) {
        // 检查文件名
        String originalFilename = StringUtils.cleanPath(Objects.requireNonNull(file.getOriginalFilename()));
        
        // 检查文件是否为空
        if (file.isEmpty()) {
            throw new RuntimeException("文件为空，无法上传");
        }
        
        // 检查文件名是否包含无效字符
        if (originalFilename.contains("..")) {
            throw new RuntimeException("文件名包含无效路径序列 " + originalFilename);
        }

        try {
            // 生成唯一的文件名
            String fileExtension = getFileExtension(originalFilename);
            String fileName = UUID.randomUUID() + fileExtension;
            
            // 调用领域层保存文件
            String filePath = fileStorage.storeFile(file, fileName);
            
            // 保存文件元数据到数据库
            FileEntity fileEntity = new FileEntity();
            fileEntity.setOriginalFileName(originalFilename);
            fileEntity.setStoredFileName(fileName);
            fileEntity.setFilePath(filePath);
            fileEntity.setFileSize(file.getSize());
            fileEntity.setFileType(file.getContentType());
            fileRepository.save(fileEntity);
            
            // 构建文件下载URL
            String fileDownloadUri = ServletUriComponentsBuilder.fromCurrentContextPath()
                .path("/api/files/download/")
                .path(String.valueOf(fileEntity.getId()))
                .toUriString();
            
            // 生成序列号（两位数，前导零填充）
            String id = String.format("%02d", sequenceCounter.getAndIncrement());
            
            // 创建带有ID的响应
            FileUploadResponse response = new FileUploadResponse(
                originalFilename,
                fileDownloadUri,
                file.getContentType(),
                file.getSize()
            );
            response.setID(id); // 设置ID
            
            return response;
        } catch (Exception e) {
            log.error("文件上传失败", e);
            throw new RuntimeException("文件上传失败: " + e.getMessage());
        }
    }
    
    private String getFileExtension(String fileName) {
        if (fileName.lastIndexOf(".") != -1 && fileName.lastIndexOf(".") != 0) {
            return fileName.substring(fileName.lastIndexOf("."));
        } else {
            return "";
        }
    }

    /**
     * 保存MultipartFile并返回文件实体
     * @param file 要保存的文件
     * @return 保存后的文件实体
     * @throws IOException 如果保存过程中发生IO异常
     */
    public FileEntity saveFile(MultipartFile file) throws IOException {
        // 检查文件名并生成唯一文件名
        String originalFilename = StringUtils.cleanPath(Objects.requireNonNull(file.getOriginalFilename()));
        String fileExtension = getFileExtension(originalFilename);
        String fileName = UUID.randomUUID() + fileExtension;
        
        // 创建上传目录（如果不存在）
        Path uploadPath = Paths.get(uploadDir).toAbsolutePath().normalize();
        Files.createDirectories(uploadPath);
        
        // 保存文件到服务器
        Path targetLocation = uploadPath.resolve(fileName);
        Files.copy(file.getInputStream(), targetLocation, StandardCopyOption.REPLACE_EXISTING);
        
        // 保存文件元数据到数据库
        FileEntity fileEntity = new FileEntity();
        fileEntity.setOriginalFileName(originalFilename);
        fileEntity.setStoredFileName(fileName);
        fileEntity.setFilePath(targetLocation.toString());
        fileEntity.setFileSize(file.getSize());
        fileEntity.setFileType(file.getContentType());
        
        return fileRepository.save(fileEntity);
    }
} 